package strategy

import (
	"fmt"
)

/////////////////////////////////////////
type FlyBehavior interface {
	Fly()
}

type QuackBehavior interface {
	Quack()
}

type Duck interface {
	FlyBehavior
	QuackBehavior
}

//////////////////////////////////////////

type FlyWithWings struct {
}

func (s *FlyWithWings) Fly() {
	fmt.Println("Fly with wings!")
}

type FlyNoWay struct {
}

func (s *FlyNoWay) Fly() {
	fmt.Println("Fly no way!")
}

type Quack struct {
}

func (s *Quack) Quack() {
	fmt.Println("Quack!")
}

type Squeak struct {
}

func (s *Squeak) Quack() {
	fmt.Println("Squeak!")
}

type MuteQuack struct {
}

func (s *MuteQuack) Quack() {
	fmt.Println("Mute quack!")
}

///////////////////////////////////////////

type MallardDuck struct {
	FlyBehavior
	QuackBehavior
}

func NewMallardDuck() *MallardDuck {
	ret := &MallardDuck{&FlyWithWings{}, &Quack{}}
	return ret
}

type RedHeadDuck struct {
	FlyBehavior
	QuackBehavior
}

func NewRedHeadDuck() *RedHeadDuck {
	ret := &RedHeadDuck{&FlyNoWay{}, &Quack{}}
	return ret
}

type RubberDuck struct {
	FlyBehavior
	QuackBehavior
}

func NewRubberDuck() *RubberDuck {
	ret := &RubberDuck{&FlyNoWay{}, &Squeak{}}
	return ret
}

type DecoyDuck struct {
	FlyBehavior
	QuackBehavior
}

func NewDecoyDuck() *DecoyDuck {
	ret := &DecoyDuck{&FlyNoWay{}, &MuteQuack{}}
	return ret
}
